use std::borrow::{Borrow, Cow};
use std::ffi::OsStr;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use serde::Serialize;

#[derive(Debug , Eq , PartialEq  , Hash)] 
#[repr(transparent)]  // 内存布局和唯一的非零大小字段完全一致  
pub struct Urn(Path) ;


impl Urn {
    #[inline]
    pub fn new<T: AsRef<Path> + ?Sized>(p : &T) ->  &Self {
        unsafe{
            // &Path -> *const Path -> *const Urn 第二次转化需要Path和Urn的内存分布是一样的
            // *const Urn -> Urn -> &Urn 
            &*(p.as_ref() as *const Path as *const Self) 
        }
    }
    #[inline]
    pub fn name(&self) -> Option<&OsStr> { 
        self.0.file_name() 
    }
    
    
    // 返回当前路径的编码字节表示  返回一个字节切片 表示路径的原始字节数据
    #[inline] 
    pub fn encoded_bytes(&self) -> &[u8]{
        // Path -> OsStr -> 底层字节表示(unix一般是utf-8)
        self.0.as_os_str().as_encoded_bytes()  
    }
    
    // 检查当前路径是否是一个隐藏的文件或者目录
    #[cfg(unix)]
    #[inline]
    pub fn is_hidden(&self) -> bool {
        use std::os::unix::ffi::OsStrExt; 
        self.name().is_some_and(|s| s.as_bytes().starts_with(b"."))
    }
}

impl Deref for Urn {
    type Target = Path;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl AsRef<Path> for Urn {
    fn as_ref(&self) -> &Path {
        &self.0
    }
}
impl ToOwned for Urn {
    type Owned = UrnBuf;
    fn to_owned(&self) -> Self::Owned {
        UrnBuf(self.0.to_owned())
    }
}
impl PartialEq<OsStr> for Urn { 
    fn eq(&self, other: &OsStr) -> bool {
        self.0 == other
    }
}

impl PartialEq<Cow<'_ , OsStr>> for &Urn {
    fn eq(&self, other: &Cow<'_, OsStr>) -> bool {
        self.0 == other.as_ref()
    }
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub  struct UrnBuf(PathBuf) ;

impl UrnBuf {
    #[inline]
    pub fn as_urn(&self) -> &Urn {
        self.borrow() 
    }
}
impl Borrow<Urn> for UrnBuf {
    fn borrow(&self) -> &Urn {
        Urn::new(&self.0)
    }
}